<script setup>
import { ref, onMounted } from 'vue';
import { message } from 'ant-design-vue';
import axios from 'axios'

const showHint = ref(false); // 提示显示与否
const hintText = ref(''); // 提示内容
const hintPosition = ref(''); // 提示位置
const currentNodeKey = ref(null); // 提示的目标节点
const node = ref(null); // 目标节点
const gData = ref([])

// 添加层级处理
const arrayFlagLevel = (array, level) => {
  if (!array || !array.length) return;
  array.forEach(item => {
    item.level = level;
    if (item.children && item.children.length) {
      arrayFlagLevel(item.children, level + 1)
    }
  })
  return array
}

// 拖拽中
const onDragover = (info) => {
  const { event, node } = info;
  const { clientY } = event;
  const rect = event.currentTarget.getBoundingClientRect();
  const offsetY = clientY - rect.top;
  const height = rect.height;
  
  currentNodeKey.value = node.eventKey;
  showHint.value = true;

  if (offsetY < (height / 2) - 1) {
    hintText.value = `将放置在【${node.title}】的上方`;
    hintPosition.value = 'top';
  } else if (offsetY > (height * 2) / 3) {
    hintText.value = `将放置在【${node.title}】的下方`;
    hintPosition.value = 'bottom';
  } else {
    hintText.value = `将与【${node.title}】合并`;
    hintPosition.value = 'middle';
  }
}

// 拖拽结束
const onDragEnter = (info) => {
  showHint.value = false;
  node.value = info.node
}

// 拖拽逻辑
const onDrop = (info) => {
  showHint.value = false;
  const dropKey = info.node.key; // 落下的节点
  const dragKey = info.dragNode.key; // 拖拽的节点
  const dropPos = info.node.pos.split('-');
  const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1]);
  
  // 判断是否同级（根据实际目标节点判断）
  if (info.dragNode.level !== node.value.level) {
    message.error('不能跨级移动！')
    return
  }

  const loop = (data, key, callback) => {
    data.forEach((item, index) => {
      if (item.key === key) {
        return callback(item, index, data);
      }
      if (item.children) {
        return loop(item.children, key, callback);
      }
    });
  };
  const data = [...gData.value];

  let dragObj;
  loop(data, dragKey, (item, index, arr) => {
    arr.splice(index, 1);
    dragObj = item;
  });

  // 合并
  if (hintPosition.value === 'middle') {
    loop(data, dropKey, item => {
      item.children = item.children || [];
      item.children.unshift(dragObj);
    })
  } else {
    // 放置：上方、下方
    if (!info.dropToGap) {
      // 落入节点(默认)和拖拽节点为同级，则移动位置；不同级，则作为子级
      if (info.dragNode.level !== info.node.level) {
        loop(data, dropKey, item => {
          item.children = item.children || [];
          item.children.unshift(dragObj);
        });
      } else {
        let ar = [];
        let i = 0;
        loop(data, dropKey, (_item, index, arr) => {
          ar = arr;
          i = index;
        });
        ar.splice(i + 1, 0, dragObj);
      }
    } else {
      console.log((info.node.children || []).length > 0, info.node.expanded, dropPosition === 1)
      /** 
       * 这里还没想好怎么处理，暂时先对其进行拦截,避免跨级移动
      */
      if (info.dragNode.level !== info.node.level) {
        message.error('不能跨级移动！')
        return
      }

      let ar = [];
      let i = 0;
      loop(data, dropKey, (_item, index, arr) => {
        ar = arr;
        i = index;
      });
      if (dropPosition === -1) {
        ar.splice(i, 0, dragObj);
      } else {
        ar.splice(i + 1, 0, dragObj);
      }
    }
  }
  gData.value = arrayFlagLevel(data, 0);
}

onMounted(() => {
  console.log('获取数据')
  axios.get('/api/tree/getTreeData').then(res => { 
    if (res.data.code === 200) {
      gData.value = arrayFlagLevel(res.data.data, 0)
    }
  })
})
</script>

<template>
  <main class="demo-tree">
    <a-tree
      draggable
      block-node
      show-line
      :tree-data="gData"
      @dragover="onDragover"
      @dragenter="onDragEnter"
      @drop="onDrop"
    >
      <template #title="{title, key}">
        <div class="node-container">
          <span>{{title}}</span>
          <div v-if="showHint && currentNodeKey === key" class="drag-hint" :class="hintPosition">{{ hintText }}</div>
        </div>
      </template>
    </a-tree>
  </main>
</template>

<style scoped>
.node-container {
  position: relative;
  width: 100%;
}

.drag-hint {
  position: absolute;
  left: 0;
  right: 0;
  padding: 4px 8px;
  background: #1890ff;
  border: 1px solid #1890ff;
  border-radius: 4px;
  color: #ffffff;
  z-index: 999;
  display: table;
}

.drag-hint.top {
  top: -30px;
}

.drag-hint.bottom {
  bottom: -30px;
}

.drag-hint.middle {
  top: 50%;
  transform: translateY(-50%);
}
</style>